package com.wao.base.hibernate.convert;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

@SuppressWarnings("unchecked")
public abstract class AbstractArrayConverter<T> {

    public static final String SEPARATOR = AbstractCollectionConverter.SEPARATOR;

    private Class<T> clazz;

    public AbstractArrayConverter() {
        clazz = (Class<T>) getGenericClass(getClass(), null, 0);
    }

    public String convertToDatabaseColumn(T[] array) {
        if (array == null)
            return null;
        if (array.length == 0)
            return "";
        return StringUtils.join(array, SEPARATOR);
    }

    public T[] convertToEntityAttribute(String string) {
        if (string == null)
            return null;
        if (string.isEmpty())
            return (T[]) Array.newInstance(clazz, 0);
        String[] arr = string.split(SEPARATOR + "\\s*");
        T[] array = (T[]) Array.newInstance(clazz, arr.length);
        for (int i = 0; i < arr.length; i++)
            array[i] = convert(arr[i]);
        return array;
    }

    protected abstract T convert(String s);

    private Class<?> getGenericClass(Class<?> clazz, Class<?> genericContainerClass, int index) {
        Type t = clazz.getGenericSuperclass();
        while (t != null) {
            if (t instanceof ParameterizedType) {
                ParameterizedType paramType = (ParameterizedType) t;
                if (genericContainerClass == null || genericContainerClass == paramType.getRawType()) {
                    return getGenericClass(paramType, index);
                } else {
                    t = paramType.getRawType();
                }
            } else if (t instanceof Class) {
                t = ((Class<?>) t).getGenericSuperclass();
            }
        }
        return null;
    }

    private Class<?> getGenericClass(Type genType, int index) {
        if (genType instanceof ParameterizedType) {
            ParameterizedType pramType = (ParameterizedType) genType;
            Type[] params = pramType.getActualTypeArguments();
            if ((params != null) && (params.length > index))
                return params[index] instanceof Class ? (Class<?>) params[index] : null;
        }
        return null;
    }

}
